home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
escalant
/
escala21.lha
/
escalante2.1
/
src
/
gm
/
GraphElement.h
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-15
|
14KB
|
568 lines
//
// Copyright (C) 1993 Jeff McWhirter
//
#ifndef <P>GraphElement_h
#define <P>GraphElement_h
#include "EscalanteGlobal.h"
#include "GraphObject.h"
#include "CommonElt.h"
#include "ObjList.h"
class Class;
//class defs
class <P>Relation;
class <P>GraphElement;
void WriteOut<PP>Set(OStream & o);
void ReadIn<PP>Set(IStream & o);
extern bool g<PP>SetIO;
extern ObjList * g<PP>ProtoList;
void SetCurrent<PP>GraphElementSet(Set *s);
Set * Get<PP>GraphElementSet();
void Kill<PP>GraphElements();
Set * Get<PP>DieSet();
void SetCurrent<PP>DieSet(Set * s);
void In<PP>Die(bool f);
void Start<PP>Die();
void End<PP>Die();
#define <PP>ITERDEP(element,ename,rname,dir,dep,deptype) {\
Iter eltloopiter((element)->GetRelations(dir));\
while(rname=(<PP>Relation*)eltloopiter()) \
if(rname->GetEventDep(dep,deptype)){\
ename = (<PP>GraphElement*)rname->GetOtherElement((element));
#define END<PP>ITERDEP }}
enum <P>GraphElementFlags{
e<P>GEPropagating = BIT(eGOLast+1),
e<P>GECopied = BIT(eGOLast+2),
e<P>Adding = BIT(eGOLast+3),
e<P>OkToWriteOut = BIT(eGOLast+4),
e<P>OkToWriteOut2 = BIT(eGOLast+5),
e<P>GraphElementLast = eGOLast+5
};
//Propagation stuff
typedef bool (*<PP>PropFunc)(<P>GraphElement*root,
<P>Relation* rel, <P>GraphElement* target,
void * data,
int hops ,
bool & b
);
typedef bool (*<PP>PathFunc)(<P>GraphElement*root,
<P>Relation* rel, <P>GraphElement* target,
void * data, int hops
);
typedef bool (*<P>RelationOKFunc)(<P>Relation*,void* );
#define <P>GraphElement_BASE GraphObject
//
//The following objects are group objects and are used to group a set
//of incident relations or the connected elements of incident relations.
//The OkToAdd Objects are used to determine if it is ok to add and element
//to a group. The OkToAdd class determines whether we are grouoing input or
//output relations. The RelXElt class decides based on the type of
//relation and element.
//
//The group objects take use an OkToAdd object to determine when an element
//should be added to a group.
//The Group::relProto and Group::firstProto attributes are ptrs to relations.
//The firstProto is used to add a relation between the element and the first element
//in the group. The relProto is used to add relations between each successive element
//in the group
//
//The RelGroup groups incident relations the EltGroup groups the other elements
//of incident relations
//
#ifdef USEGROUP
class <PP>OkToAdd: public Object{
public:
RDir dir;
MetaDef(<PP>OkToAdd);
<PP>OkToAdd(RDir d = eInOut){dir = d;}
virtual bool InRelationOk(<P>Relation *){
return (dir== eIn || dir == eInOut);
}
virtual bool OutRelationOk(<P>Relation *){
return (dir== eOut || dir == eInOut);
}
virtual bool HeadOk(<P>GraphElement *,<P>Relation *){
return (dir== eOut || dir == eInOut);
}
virtual bool TailOk(<P>GraphElement *,<P>Relation *){
return (dir== eIn || dir == eInOut);
}
OStream& PrintOn(OStream&);
IStream& ReadFrom(IStream&);
};
class <PP>RelXElt: public <PP>OkToAdd{
public:
class Class* relc;
class Class* eltc;
MetaDef(<PP>RelXElt);
<PP>RelXElt(Class * r,Class * e=0,RDir dir = eInOut):<PP>OkToAdd(dir){
relc =r; eltc=e;
}
bool InRelationOk(<P>Relation * );
bool OutRelationOk(<P>Relation *);
bool HeadOk(<P>GraphElement * ,<P>Relation * );
bool TailOk(<P>GraphElement * ,<P>Relation * );
OStream& PrintOn(OStream&);
IStream& ReadFrom(IStream&);
};
enum <PP>GroupFlags{
e<PP>KillRel = BIT(eGOLast+1),
e<PP>GroupLast = eGOLast+1};
class <PP>Group: public Object{
public:
int id;
<PP>OkToAdd * criteria;
<P>GraphElement * theelt;
<P>Relation * relProto;
<P>Relation * firstProto;
ObjList* elts;
MetaDef(<PP>Group);
void InitClone(){elts=0;}
<PP>Group(<P>GraphElement * telt,<P>Relation * proto,<PP>OkToAdd * crit=0,<P>Relation * fp=0){
theelt= telt;relProto = proto;criteria = crit;elts=0; firstProto=fp;
}
~<PP>Group();
void DoObserve(int id, int part, void *d , Object *op);
int GetId(){return id;}
void SetId(int i){id =i;}
virtual void AddElement(<P>GraphElement*);
virtual void RemoveElement(<P>GraphElement * );
void SetElement(<P>GraphElement * elt){theelt = elt;}
virtual void AddedInRelation(<P>Relation * ){}
virtual void RemovedInRelation(<P>Relation * ){}
virtual void AddedOutRelation(<P>Relation * ){}
virtual void RemovedOutRelation(<P>Relation *){}
virtual void NewTail(<P>Relation * ,<P>GraphElement* ,<P>GraphElement*){}
virtual void NewHead(<P>Relation * ,<P>GraphElement*,<P>GraphElement* ){}
void Connect(<P>GraphElement * e1,<P>GraphElement * e2);
OStream& PrintOn(OStream&);
IStream& ReadFrom(IStream&);
};
class <PP>RelGroup: public <PP>Group{
public:
MetaDef(<PP>RelGroup);
<PP>RelGroup(class <P>GraphElement * telt,<P>Relation * proto,class <PP>OkToAdd * cl,<P>Relation* firstProto =0):
<PP>Group(telt,proto,cl,firstProto){}
void RemovedInRelation(<P>Relation * r){RemoveElement((<P>GraphElement*)r );}
void RemovedOutRelation(<P>Relation * r){RemoveElement((<P>GraphElement*)r);}
void AddedRelation(<P>Relation * r,RDir dir);
void AddedInRelation(<P>Relation * r){AddedRelation(r,eIn);}
void AddedOutRelation(<P>Relation * r){AddedRelation(r,eOut);}
};
class <PP>EltGroup: public <PP>Group{
public:
MetaDef(<PP>EltGroup);
<PP>EltGroup(class <P>GraphElement * telt,<P>Relation * proto,class <PP>OkToAdd * cl,<P>Relation* firstProto=0):
<PP>Group(telt,proto,cl,firstProto){}
void RemovedInRelation(<P>Relation * r);
void RemovedOutRelation(<P>Relation * r);
void AddedInRelation(<P>Relation * r);
void AddedOutRelation(<P>Relation * r);
void NewElt(RDir dir,<P>Relation *r ,<P>GraphElement* newtl,<P>GraphElement* oldtl =0);
void NewTail(<P>Relation *r ,<P>GraphElement* newtl,<P>GraphElement* oldtl =0){
NewElt(eIn,r,newtl,oldtl);
}
void NewHead(<P>Relation *r ,<P>GraphElement* newhd,<P>GraphElement* oldhd =0 ){
NewElt(eOut,r,newhd,oldhd);
}
};
#endif USEGROUP
class <P>GraphElement: public GraphObject{
public:
//
//A list of prototypes for this element. Used in the EscalanteView palette and
//for adding elements and finding default relations
//
ObjList * protos;
//
//The incoming and outgoing relations. An InRel is one in which this
//element is the hd of the relations. OutRel -> this element is the tail
//
ObjList * InRels;
ObjList * OutRels;
//
//Used in event propagation
//
long int eventMask;
long int affectedByEvents;
char * name;
MetaDef(<P>GraphElement);
virtual <P>Relation * GetDefaultMemberOf(){return 0;}
<P>GraphElement();
~<P>GraphElement();
void InitClone();
#ifdef USEGROUP
//
//Group stuff
//
ObjList * groups;
void AddGroup(<PP>Group * g){
if(groups == 0) groups = new ObjList();
groups->Add(g);
g->SetElement(this);
}
<PP>Group * GetGroupWithId(int i);
#endif USEGROUP
virtual void AddGroupRelation(<P>Relation * r);
virtual char * GetDescription(){return 0;}
bool GetAdding(){return TestFlag(e<P>Adding);}
virtual void SetAdding(bool b){SetFlag(e<P>Adding,b);}
void SetName(char * nl){
strreplace(&name,nl);
SAC(<P>GraphElement,name);
}
char * GetName(){return name;}
void * DoEvent2(Events event, <P>GraphElement * elt, void * data, ObjList * list );
virtual void *DoEvent(Events event, <P>GraphElement * elt =0, void * data=0);
bool DoneEvent(Events event) {return TestMask(eventMask,event);}
void SetEvent(Events event) {SetMask(eventMask,event);}
void ClearEvent(Events event = eEventNull) {
if(event == eEventNull) eventMask= 0;
else ResetMask(eventMask,event);
}
void * PropagateEvent(Events event,Events notevents, <P>GraphElement * elt =0, void * data =0,ObjList * list = 0);
virtual void * PropagateEvent2(Events event,Events notevents, <P>GraphElement * elt =0, void * data =0,ObjList * list = 0);
void * PropagateEvent(Events event, <P>GraphElement * elt, void * data =0,ObjList * list = 0){
return PropagateEvent( event,(Events)0,elt, data , list );
}
void* GetAttribute(int aid,DataType & type);
void ChangeAttribute(int aid, void * data, DataType type);
void SendAttributeChange(int aid, void * data=0,DataType type = eNullAttrType);
void NewProtos(){protos = new ObjList();}
void AddPrototype(<P>GraphElement *e){if(!protos) NewProtos();protos->Add((Object*)e);}
<P>GraphElement* GetPrototype(<P>GraphElement *e){return (protos?
((protos->Contains((Object*)e))? e:0):
0);}
<P>GraphElement* GetPrototypeOfClass(class Class * c);
ObjList * GetPrototypes(){return protos;}
virtual bool AddOnlyIfHaveProto(){return FALSE;}
virtual bool AddOnlyIfHaveDflt(){return FALSE;}
virtual bool AddOnCloning(){return TRUE;}
bool OkToWriteOut(){
return (IfFalseDontWriteOutOriginal() &&
IfFalseDontWriteOutClone() &&
!IsDead());
}
bool IfFalseDontWriteOutOriginal(){return TestFlag(e<P>OkToWriteOut);}
void IfFalseDontWriteOutOriginal(bool f){SetFlag(e<P>OkToWriteOut,f);}
bool IfFalseDontWriteOutClone(){return TestFlag(e<P>OkToWriteOut2);}
void IfFalseDontWriteOutClone(bool f){SetFlag(e<P>OkToWriteOut2,f);}
void Die();
void SetDead(bool f);
virtual void MS_Die(){}
bool Copied(){return TestFlag(e<P>GECopied);}
void Copied(bool f){SetFlag(e<P>GECopied,f);}
<P>GraphElement * Copy();
//
//Function propagation stuff
//
//
//You can give an element a function to propagate along its incident
//relations. The first PFunc lets you specify a function (func)
//and data to pass to the function (funcdata)
//the type of relations and elements to propagate along (relc,eltc),
//how many hops (maxhops) to go, and the direction of propagation.
//The function takes the following parameters:
//typedef bool (*<PP>PropFunc)(<P>GraphElement*root,
// <P>Relation* rel, <P>GraphElement* target,
// void * data,
// int hops ,
// bool & b
// );
//Where root is the original element called. rel and target are
//the relation and the target element of the relation,
//hops is the hops so far
//b if FALSE then we exit the entire propagation
//If the function returns FALSE then we don't continue
//propagation with the target
//The second PFunc method lets you specify a function (path) and
//data to pass to that functin (pathdata). This function decides
//which is an ok path to go on.
//
bool Propagating(){return TestFlag(e<P>GEPropagating);}
void Propagating(bool f){SetFlag(e<P>GEPropagating,f);}
bool PFunc(<PP>PropFunc func,
void * funcdata,
class Class* relc,
class Class* eltc,
int maxhops = MAXINT,
RDir dir= eInOut);
bool PFunc( <PP>PropFunc func ,
void * funcdata,
int maxhops = MAXINT,
RDir dir= eInOut,
<PP>PathFunc path =0 ,
void * pathdata = 0,
ObjList * l =0,
int hopssofar = 0);
OStream& PrintOn(OStream&);
IStream& ReadFrom(IStream&);
//
//These can get called when looking for and element to set the tl or head
//of a relation (in EscalanteView)
//
virtual bool OkToAddInRelation(<P>Relation * r){return TRUE;}
virtual bool OkToAddOutRelation(<P>Relation * r){return TRUE;}
//
//These methods move in/out relation ptrs to the front/back of the list
//
void MoveRelation(<P>Relation * r, RDir dir,bool tofront= TRUE);
void InRelationToFront(<P>Relation * r){MoveRelation(r,eIn,TRUE);}
void InRelationToBack(<P>Relation * r){MoveRelation(r,eIn,FALSE);}
void OutRelationToFront(<P>Relation * r){MoveRelation(r,eOut,TRUE);}
void OutRelationToBack(<P>Relation * r){MoveRelation(r,eOut,FALSE);}
//
//These methods return the predecessor/successor (e.g. tl of in rel, hd of out rel)
//for relations of type relClass and pred/succ of type eltClass
//rIsKindOf and eIsKindOf are flags that signal how to check - using IsKindOf or IsA
//
<P>GraphElement * Pred(class Class *relClass=0,
class Class * eltClass=0,
bool rIsKindOf = TRUE,
bool eIsKindOf = TRUE);
<P>GraphElement * Succ(class Class *relClass=0,
class Class * eltClass=0,
bool rIsKindOf = TRUE,
bool eIsKindOf = TRUE);
//
//These methods are just like the ones above except return the relation
//
<P>Relation * RelPred(class Class *relClass=0,
class Class * eltClass=0,
bool rIsKindOf = TRUE,
bool eIsKindOf = TRUE);
<P>Relation * RelSucc(class Class *relClass=0,
class Class * eltClass=0,
bool rIsKindOf = TRUE,
bool eIsKindOf = TRUE);
void Pred(Class *relClass,
Class * eltClass,
<P>Relation*&,
<P>GraphElement*&,
bool rIsKindOf,
bool eIsKindOf);
void Succ(Class *relClass,
Class * eltClass,
<P>Relation*&,
<P>GraphElement*&,
bool rIsKindOf,
bool eIsKindOf);
//
//Incident relation stuff
//
//
//Getting new relations and tails/heads
//
virtual void AddInRelation(<P>Relation *r);
virtual void RemoveInRelation(<P>Relation *r);
virtual void AddOutRelation(<P>Relation *r);
virtual void RemoveOutRelation(<P>Relation *r);
virtual void NewTail(<P>Relation * r, <P>GraphElement * newtl=0,<P>GraphElement* oldtl =0);
virtual void NewHead(<P>Relation * r, <P>GraphElement * newhd=0,<P>GraphElement* oldhd =0);
//
//Return the correct list of relations
//
ObjList * GetRelations(RDir dir = eIn){return (dir == eIn ? InRels : OutRels);}
//
//This find a relation of type c with other element == elt
//
<P>Relation * GetRelation(<P>GraphElement*elt ,
RDir dir = eIn,
class Class * c = 0,
bool rIsKindOf =TRUE);
//
//This finds the incident relations with a certain dependency set
//
void GetRelsWithDep(ObjList & l, Events events, DepTypes type,RDir dir);
//
//This gets called by an incident relation when some event dependency changes
//
virtual void DepChange(Events event, DepTypes type){}
//
//This searches through the protos list trying to find some relation of
//type rc with tail and head of the same type of the tl and hd args.
//
<P>Relation * GetDefaultRelation(<P>GraphElement * tl,
<P>GraphElement * hd,
class Class * rclass = 0 );
//
//These methods are used to add an element to this element.
//This adding is in effect adding a new relation between this element
//and the new element
//
void AddElement(<P>GraphElement * elt, <P>Relation * rel =0 );
void AddElements(Set *s);
};
#endif <P>GraphElement_h